package mail;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Properties;

import mail.bean.AccountBean;
import mail.bean.EmailBean;
import mail.security.SecurityManager;

public class AccountManager {
  public final static String MAIL_HOST="mail.host";
  public final static String MAIL_STORE_PROTOCOL="mail.store.protocol";
  public final static String MAIL_POP3_HOST="mail.pop3.host";
  public final static String MAIL_POP3_PORT="mail.pop3.port";
  public final static String MAIL_POP3_SOCKETFACTORY_CLASS="mail.pop3.socketFactory.class";
  public final static String MAIL_POP3_SOCKETFACTORY_FALLBACK="mail.pop3.socketFactory.fallback";
  public final static String MAIL_POP3_SOCKETFACTORY_PORT="mail.pop3.socketFactory.port";
  public final static String MAIL_TRANSPORT_PROTOCOL="mail.transport.protocol";
  public final static String MAIL_SMTP_HOST="mail.smtp.host";
  public final static String MAIL_SMTP_PORT="mail.smtp.port";
  public final static String MAIL_SMTP_SOCKETFACTORY_CLASS="mail.smtp.socketFactory.class";
  public final static String MAIL_SMTP_SOCKETFACTORY_FALLBACK="mail.smtp.socketFactory.fallback";
  public final static String MAIL_SMTP_SOCKETFACTORY_PORT="mail.smtp.socketFactory.port";
  public final static String MAIL_SMTP_AUTH="mail.smtp.auth";
  
  public final static String ACCOUNT = "account";
  private final static String configFile = "email.properties";
  
  public static void main(String[] args) {
    File inboxFolder = new File("./zjyzju@gmail.com/inbox");
    if(inboxFolder.isDirectory()) {
      System.out.println("is directory");
      FilenameFilter filter = new FilenameFilter() {
        public boolean accept(File dir, String name) {
          if(name != null && name.endsWith(".mail")) {
            return true;
          }
          return false;
        }
      };
      File[] names = inboxFolder.listFiles(filter);
      for(File name : names) {
        System.out.println(name.getAbsolutePath() + ":" + name.getName());
      }
    }
  }
  
  public static ArrayList<EmailBean> loadMailList(String inboxPath) {
    ArrayList<EmailBean> mailList = new ArrayList<EmailBean>();
    File inboxFolder = new File(inboxPath);
    if(inboxFolder.isDirectory()) {
      FilenameFilter filter = new FilenameFilter() {
        public boolean accept(File dir, String name) {
          if(name != null && name.endsWith(".mail")) {
            return true;
          }
          return false;
        }
      };
      File[] mails = inboxFolder.listFiles(filter);
      if (mails != null && mails.length > 0) {       
        ObjectInputStream ois = null;
        EmailBean bean = null;
        try {
          for(File mail : mails) {
            if(mail.isFile()) {
              ois = new ObjectInputStream(new FileInputStream(mail));
              bean = (EmailBean)ois.readObject();
              mailList.add(bean);
              ois.close();
              ois = null;
            }
          }
        } catch (Exception e) {
          e.printStackTrace();
          return null;
        } finally {
          if(ois != null) {
            try {
              ois.close();
            } catch (IOException e) {
              e.printStackTrace();
            }
          }
        }
      }
    }
    return mailList;
  }
  
  public static ArrayList<String> getUidList(ArrayList<EmailBean> mailList) {
    if(mailList == null) {
      return null;
    }
    ArrayList<String> uidList = new ArrayList<String>();   
    for(EmailBean bean : mailList) {
      uidList.add(bean.getUid());
    }
    return uidList;
  }
  
  public static ArrayList<AccountBean> loadAccount() {
    Properties prpt = load(configFile);
    boolean more = true;
    int i = 1;
    String property = null;
    String value = null;
    ArrayList<AccountBean> accounts = new ArrayList<AccountBean>();
    AccountBean account = null;
    Properties env = null;
    while(more) {
      property = ACCOUNT + i++;
      value = prpt.getProperty(property + ".name");
      if(value != null && value.trim().length() != 0) {
        account = new AccountBean(value);
        env = new Properties();
        
        value = prpt.getProperty(property + ".address");
        if(value != null && value.trim().length() != 0) {
          account.setAccountAddress(value);
          account.setSaveFolder("./" + account.getAccountAddress());
          new File(account.getSaveFolder()).mkdir();
        }
        
        value = prpt.getProperty(property + ".store.protocol");
        if(value != null && value.trim().length() != 0) {
          account.setRecProtocol(value);
          env.put(MAIL_STORE_PROTOCOL, value);
        }
        
        value = prpt.getProperty(property + ".pop3.host");
        if(value != null && value.trim().length() != 0) {
          account.setRecHost(value);
          env.put(MAIL_POP3_HOST, value);
        }
        
        value = prpt.getProperty(property + ".pop3.port");
        if(value != null && value.trim().length() != 0) {
          account.setRecPort(value);
          env.put(MAIL_POP3_PORT, value);
          env.put(MAIL_POP3_SOCKETFACTORY_PORT, value);
        }
        
        value = prpt.getProperty(property + ".pop3.ssh");
        if(value != null && value.trim().length() != 0) {
          account.setPop3UseSSH(Boolean.parseBoolean(value));
          if(account.isPop3UseSSH()) {
            env.put(MAIL_POP3_SOCKETFACTORY_FALLBACK, "false");
          }
        }
        
        value = prpt.getProperty(property + ".transport.protocol");
        if(value != null && value.trim().length() != 0) {
          account.setSendProtocol(value);
          env.put(MAIL_TRANSPORT_PROTOCOL, value);
        }
        
        value = prpt.getProperty(property + ".smtp.host");
        if(value != null && value.trim().length() != 0) {
          account.setSendHost(value);
          env.put(MAIL_SMTP_HOST, value);
        }
        
        value = prpt.getProperty(property + ".smtp.port");
        if(value != null && value.trim().length() != 0) {
          account.setSendPort(value);
          env.put(MAIL_SMTP_PORT, value);
          env.put(MAIL_SMTP_SOCKETFACTORY_PORT, value);
        }
        
        value = prpt.getProperty(property + ".smtp.auth");
        if(value != null && value.trim().length() != 0) {
          account.setNeedAuth(Boolean.parseBoolean(value));
          env.put(MAIL_SMTP_AUTH, value);
        }
        
        value = prpt.getProperty(property + ".smtp.ssh");
        if(value != null && value.trim().length() != 0) {
          account.setSmtpUseSSH(Boolean.parseBoolean(value));
          if(account.isSmtpUseSSH()) {
            env.put(MAIL_SMTP_SOCKETFACTORY_FALLBACK, "false");
          }
        }
        
        value = prpt.getProperty(property + ".ssl.socketFactory.class");
        if(value != null && value.trim().length() != 0) {
          account.setSslSocletFactory(value);
          env.put(MAIL_POP3_SOCKETFACTORY_CLASS, value);
          env.put(MAIL_SMTP_SOCKETFACTORY_CLASS, value);
        }
        value = prpt.getProperty(property + ".user");
        if(value != null && value.trim().length() != 0) {
          account.setUser(value);
        }        
        value = prpt.getProperty(property + ".pwd");
        if(value != null && value.trim().length() != 0) {
          account.setPwd(SecurityManager.decryptDES(value));
        }
        account.setEnv(env);
        accounts.add(account);
      }else {
        more = false;
      }
    }
    return accounts;
  }
  
  public static boolean saveAccount(ArrayList<AccountBean> accounts) {
    if(accounts != null && accounts.size() >0 ) {
      int i = 1;
      String property = null;
      String value = null;
      Properties prpt = null;
      FileOutputStream fos = null;
      try {
        fos = new FileOutputStream(configFile);
        for(AccountBean account : accounts) {
          prpt = new Properties();
          property = ACCOUNT + i++;
          value = account.getAccountName();
          if(value != null && value.trim().length() != 0) {
            prpt.setProperty(property + ".name", value);
          }
          value = account.getAccountAddress();
          if(value != null && value.trim().length() != 0) {
            prpt.setProperty(property + ".address", value);
          }
          value = account.getRecProtocol();
          if(value != null && value.trim().length() != 0) {
            prpt.setProperty(property + ".store.protocol", value);
          }
          value = account.getRecHost();
          if(value != null && value.trim().length() != 0) {
            prpt.setProperty(property + ".pop3.host", value);
          }
          value = account.getRecPort();
          if(value != null && value.trim().length() != 0) {
            prpt.setProperty(property + ".pop3.port", value);
          }
          value = "" + account.isPop3UseSSH();
          if(value != null && value.trim().length() != 0) {
            prpt.setProperty(property + ".pop3.ssh", value);
          }
          value = account.getSendProtocol();
          if(value != null && value.trim().length() != 0) {
            prpt.setProperty(property + ".transport.protocol", value);
          }
          value = account.getSendHost();
          if(value != null && value.trim().length() != 0) {
            prpt.setProperty(property + ".smtp.host", value);
          }
          value = account.getSendPort();
          if(value != null && value.trim().length() != 0) {
            prpt.setProperty(property + ".smtp.port", value);
          }
          value = "" + account.isNeedAuth();
          if(value != null && value.trim().length() != 0) {
            prpt.setProperty(property + ".smtp.auth", value);
          }
          value = "" + account.isSmtpUseSSH();
          if(value != null && value.trim().length() != 0) {
            prpt.setProperty(property + ".smtp.ssh", value);
          }
          value = account.getSslSocletFactory();
          if(value != null && value.trim().length() != 0) {
            prpt.setProperty(property + ".ssl.socketFactory.class", value);
          }
          value = account.getUser();
          if(value != null && value.trim().length() != 0) {
            prpt.setProperty(property + ".user", value);
          }
          value = account.getPwd();
          if(value != null && value.trim().length() != 0) {
            prpt.setProperty(property + ".pwd", SecurityManager.encryptDES(value));
          }
          prpt.store(fos, "Account:" + account.getAccountName());
        }      
        return true;
      }catch(Exception e) {
        e.printStackTrace();
        return false;
      }finally {
        try {
          fos.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
    return true;
  }
  
  public static Properties load(String fileName) {
    Properties prpt = new Properties();
    InputStream is = null;
    try {
      is = new FileInputStream(fileName);
      if(is == null) {
        return null;
      }
      prpt.load(is);
    } catch (IOException e) {
      e.printStackTrace();
      return null;
    } finally {
      try {
        is.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    return prpt;
  }
  
  public static Properties loadClassPath(String fileName) {
    Properties prpt = new Properties();
    InputStream is = AccountManager.class.getClassLoader().getResourceAsStream(fileName);
    if(is == null) {
      return null;
    }
    try {
      prpt.load(is);
    } catch (IOException e) {
      e.printStackTrace();
      return null;
    } finally {
      try {
        is.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    return prpt;
  }
  
}
